from sklearn.svm import SVR
from dateutil import parser
import matplotlib.dates as mdates
import matplotlib.pyplot as plt
import numpy as numpy
import numpy as np
import pandas as pd
import datetime
from scipy.optimize import root, fsolve


# 收集 10 个城市的最高温和最低温，
# 用线性图表示气温最值点和离海远近之间的关系。

df_ferrara = pd.read_csv('main/ferrara_270615.csv')
df_milano = pd.read_csv('main/milano_270615.csv')
df_mantova = pd.read_csv('main/mantova_270615.csv')
df_ravenna = pd.read_csv('main/ravenna_270615.csv')
df_torino = pd.read_csv('main/torino_270615.csv')
df_asti = pd.read_csv('main/asti_270615.csv')
df_bologna = pd.read_csv('main/bologna_270615.csv')
df_piacenza = pd.read_csv('main/piacenza_270615.csv')
df_cesena = pd.read_csv('main/cesena_270615.csv')
df_faenza = pd.read_csv('main/faenza_270615.csv')


# 读取温度和日期数据
y1 = df_ravenna['temp']
x1 = df_ravenna['day']
y2 = df_faenza['temp']
x2 = df_faenza['day']
y3 = df_cesena['temp']
x3 = df_cesena['day']
y4 = df_milano['temp']
x4 = df_milano['day']
y5 = df_asti['temp']
x5 = df_asti['day']
y6 = df_torino['temp']
x6 = df_torino['day']

# 把日期从string类型转化为标准的datetime类型
day_ravenna = [parser.parse(x) for x in x1]
day_faenza = [parser.parse(x) for x in x2]
day_cesena = [parser.parse(x) for x in x3]
day_milano = [parser.parse(x) for x in x4]
day_asti = [parser.parse(x) for x in x5]
day_torino = [parser.parse(x) for x in x6]


# dis是一个装城市距离海边距离的列表
dist = [df_ravenna['dist'][0],
        df_cesena['dist'][0],
        df_faenza['dist'][0],
        df_ferrara['dist'][0],
        df_bologna['dist'][0],
        df_mantova['dist'][0],
        df_piacenza['dist'][0],
        df_milano['dist'][0],
        df_asti['dist'][0],
        df_torino['dist'][0]
        ]

# temp_max是一个存放每个城市最高温度的列表
temp_max = [df_ravenna['temp'].max(),
            df_cesena['temp'].max(),
            df_faenza['temp'].max(),
            df_ferrara['temp'].max(),
            df_bologna['temp'].max(),
            df_mantova['temp'].max(),
            df_piacenza['temp'].max(),
            df_milano['temp'].max(),
            df_asti['temp'].max(),
            df_torino['temp'].max()
            ]

# temp_min存放最低温度的列表
temp_min = [df_ravenna['temp'].min(),
            df_cesena['temp'].min(),
            df_faenza['temp'].min(),
            df_ferrara['temp'].min(),
            df_bologna['temp'].min(),
            df_mantova['temp'].min(),
            df_piacenza['temp'].min(),
            df_milano['temp'].min(),
            df_asti['temp'].min(),
            df_torino['temp'].min()
            ]
# print(temp_min)

# 先画出最高温度
fig, ax = plt.subplots()
ax.plot(dist, temp_max, 'ro')
ax.plot(dist, temp_min, 'bo')

'''
用线性回归算法得到两条直线，
分别表示两种不同的气温趋势，这样做很有趣。
我们可以使用 scikit-learn 库的 SVR 方法。
from sklearn.svm import SVR
'''

# dist1是靠近海的城市集合,dist2是远离海洋的城市集合
dist1 = dist[0:5]  # [8, 14, 37, 47, 71]
dist2 = dist[5:10]  # [121, 200, 250, 315, 357]

# 改变列表的结构，dist1现在是5个列表的集合
# 之后我们会看到 nbumpy 中 reshape() 函数也有同样的作用
# reshape()是数组array中的方法，作用是将数据重新组织
dist1 = [[x] for x in dist1]  # [[8], [14], [37], [47], [71]]
dist2 = [[x] for x in dist2]  # [[121], [200], [250], [315], [357]]

# temp_max1 是 dist1 中城市的对应最高温度
temp_max1 = temp_max[0:5]
# temp_max2 是 dist2 中城市的对应最高温度
temp_max2 = temp_max[5:10]

# 我们调用SVR函数,在参数中规定了使用线性的拟合函数 (线性函数，则称为线性拟合.线性拟合是曲线拟合的一种形式。)
# 并且把C设为1000来尽量拟合数据(因为不需要精确预测不用担心过拟合)
svr_lin1 = SVR(kernel='linear', C=1e3)
svr_lin2 = SVR(kernel='linear', C=1e3)

# 加入数据,进行拟合(这一步可能会跑很久,大概10分钟,休息一下:)
svr_lin1.fit(dist1, temp_max1)
svr_lin2.fit(dist2, temp_max2)

# reshape函数()
xp1 = np.arange(10, 100, 10).reshape((9, 1))
xp2 = np.arange(50, 400, 50).reshape((7, 1))
yp1 = svr_lin1.predict(xp1)
yp2 = svr_lin2.predict(xp2)


# 限制了x轴的取值范围
fig, ax = plt.subplots()
ax.set_xlim(0, 400)

# 画出图像
ax.plot(xp1, yp1, c='b', label='Strong sea effect')
ax.plot(xp2, yp2, c='g', label='Light sea effect')
ax.plot(dist, temp_max, 'ro')


# print(svr_lin1.coef_)       # 斜率  [[0.04794118]]
# print(svr_lin1.intercept_)  # 截距   [27.65617647]
# print(svr_lin2.coef_)       # [[0.00401274]]
# print(svr_lin2.intercept_)  # [29.98745223]


'''
考虑将这两条直线的交点
作为受海洋影响和不受海洋影响的区域的分界点
from scipy.optimize import fsolve
'''

# 定义了第一条拟合直线


def line1(x):
    a1 = svr_lin1.coef_[0][0]
    b1 = svr_lin1.intercept_[0]
    return a1 * x + b1

# 定义了第二条拟合直线


def line2(x):
    a2 = svr_lin2.coef_[0][0]
    b2 = svr_lin2.intercept_[0]
    return a2 * x + b2


# 定义了找到两条直线的交点的x坐标的函数
def findIntersection(fun1, fun2, x0):
    return fsolve(lambda x: fun1(x) - fun2(x), x0)


result = findIntersection(line1, line2, 0.0)
# print('[x,y]=[%d,%d]' % (result, line1(result)))  # 得到交点的坐标: [x,y]=[53,30]

x = np.linspace(0, 400, 31)
plt.plot(x, line1(x), x, line2(x), result, line1(result), 'ro')

plt.show()


([[0, 0], [1, 1], [2, 2]], [0, 1, 2])
